package com.yizhang.newfeatures;

import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CompletableFutureTest {

    private static final ExecutorService executorService = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        anyOf();
    }


    public static void runAsync(){
        CompletableFuture.runAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
        }, executorService);
    }

    public static void supplyAsync() throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            return i;
        }, executorService);
        Integer i = future.get();
        System.out.println("运行结果：" + i);
    }

    public static void whenComplete() throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            return i;
        }, executorService).whenComplete((res, ex) -> {
            System.out.println("结果：" + res + " 异常：" + ex);
        }).exceptionally(throwable -> 10);
        Integer i = future.get();
        System.out.println("运行结果：" + i);
    }

    public static void handle() throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            return i;
        }, executorService).handle((res, ex) -> Objects.requireNonNullElse(res, -1));
        Integer i = future.get();
        System.out.println("运行结果：" + i);
    }

    public static void thenRunAsync() {
        CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            return i;
        }, executorService).thenRunAsync(() -> System.out.println("我完成了"), executorService);
        System.out.println("main... end ...");
    }

    public static void thenApplyAsync() throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            return i;
        }, executorService).thenApplyAsync(res -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            return res * 2;
        }, executorService);
        Integer i = future.get();
        System.out.println("main... end ..." + i);
    }

    public static void thenAcceptAsync() {
        CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            return i;
        }, executorService).thenAcceptAsync(System.out::println, executorService);
        System.out.println("main... end ...");
    }

    public static void runAfterBothAsync() {
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            return i;
        }, executorService);

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2开始");
            System.out.println("任务2结束");
            return "hello";
        }, executorService);

        future1.runAfterBothAsync(future2, () -> {
            System.out.println("任务3开始");
        }, executorService);
        System.out.println("main... end ...");
    }

    public static void thenAcceptBothAsync() {
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            return i;
        }, executorService);

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2开始");
            System.out.println("任务2结束");
            return "hello";
        }, executorService);

        future1.thenAcceptBothAsync(future2, (res1, res2) -> {
            System.out.println("结果1是：" +  res1 + " 结果2是" + res2);
        }, executorService);
        System.out.println("main... end ...");
    }

    public static void thenCombineAsync() throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            return i;
        }, executorService);

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2开始");
            System.out.println("任务2结束");
            return "hello";
        }, executorService);

        CompletableFuture<String> future = future1.thenCombineAsync(future2, (res1, res2) -> {
            System.out.println("结果1是：" + res1 + " 结果2是" + res2);
            return res1 + res2;
        }, executorService);
        String s = future.get();
        System.out.println("main... end ..." + s);
    }

    public static void runAfterEitherAsync() {
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            return i;
        }, executorService);

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2开始");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("任务2结束");
            return "hello";
        }, executorService);

        future1.runAfterEitherAsync(future2, () -> {
            System.out.println("任务3开始");
        }, executorService);
        System.out.println("main... end ...");
    }

    public static void acceptEitherAsync() {
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            return i;
        }, executorService);

        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2开始");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("任务2结束");
            return 10;
        }, executorService);

        future1.acceptEitherAsync(future2, res -> {
            System.out.println("结果是：" +  res);
        }, executorService);
        System.out.println("main... end ...");
    }

    public static void applyToEitherAsync() throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            return i;
        }, executorService);

        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2开始");
            System.out.println("任务2结束");
            return 10;
        }, executorService);

        CompletableFuture<Integer> future = future1.applyToEitherAsync(future2, res -> {
            System.out.println("结果是：" + res);
            return res * 2;
        }, executorService);
        Integer s = future.get();
        System.out.println("main... end ..." + s);
    }

    public static void allOf () throws ExecutionException, InterruptedException {
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品图片");
            return "pic";
        }, executorService);

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品名称");
            return "name";
        }, executorService);

        CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品价格");
            return "price";
        }, executorService);

        CompletableFuture<Void> future = CompletableFuture.allOf(future1, future2, future3);
        future.get();
        System.out.println("main... end ..." + future1.get() + " " + future2.get() + " " + future3.get());
    }

    public static void anyOf () throws ExecutionException, InterruptedException {
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("查询商品图片");
            return "pic";
        }, executorService);

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品名称");
            return "name";
        }, executorService);

        CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品价格");
            return "price";
        }, executorService);

        CompletableFuture<Object> future = CompletableFuture.anyOf(future1, future2, future3);
        System.out.println("main... end ..." + future.get());
    }
}
